// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) 
// Source File Name:   KeelRuntimeImpl.java

package backstage.runtime;

import backstage.gfx.NativeGLGraphics;
import backstage.gfx.SoftGLContext;
import backstage.runtime.ctrl.ControllerConfigSet;
import backstage.runtime.ctrl.ControllerDeviceConfig;
import backstage.runtime.ctrl.ControllerDeviceImpl;
import backstage.runtime.ctrl.ControllerPortManagerImpl;
import backstage.runtime.ctrl.KeyboardDeviceImpl;
import java.awt.Canvas;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import keel.gfx.GLContext;
import keel.gfx.GLGraphics;
import keel.gfx.PixelFormat;
import keel.resource.Archive;
import keel.resource.ArchiveClassLoader;
import keel.resource.Resource;
import keel.runtime.Application;
import keel.runtime.Cursor;
import keel.runtime.DisplayMode;
import keel.runtime.KeelRuntime;
import keel.runtime.audio.AudioPlayer;
import keel.runtime.ctrl.Controller;
import keel.runtime.ctrl.ControllerDescriptor;
import keel.runtime.ctrl.ControllerDeviceManager;
import keel.runtime.ctrl.ControllerPort;
import keel.runtime.ctrl.ControllerPortManager;
import keel.runtime.ctrl.KeyboardDevice;
import keel.runtime.event.ApplicationEvent;
import keel.runtime.event.ControllerEvent;
import keel.runtime.event.ControllerPortEvent;
import keel.runtime.event.Event;
import keel.runtime.event.MouseEvent;
import keel.runtime.im.ActiveInputMethodRequests;
import keel.runtime.im.PassiveInputMethodRequests;

// Referenced classes of package backstage.runtime:
//            PlatformInfo

public abstract class KeelRuntimeImpl extends KeelRuntime
{
    class GLContextRuntimeImpl extends GLContext
    {

        protected final boolean _makeCurrent()
        {
            if(KeelRuntimeImpl.this._makeCurrent())
            {
                graphicsThread = Thread.currentThread();
                return true;
            } else
            {
                return false;
            }
        }

        protected final GLGraphics createGraphics()
        {
            return new NativeGLGraphics(this);
        }

        public final void swapBuffers()
        {
            _swapBuffers();
        }

        protected final void _free()
        {
            graphicsThread = null;
            KeelRuntimeImpl.this._free();
        }

        protected final void _yield()
        {
        }

        GLContextRuntimeImpl(long ref)
            throws Exception
        {
            super(ref);
        }
    }


    protected KeelRuntimeImpl()
    {
        autoUpdate = true;
        foreprocess = true;
        glcontext = null;
        eventQueue = new ArrayList(10);
        screenwidth = 0;
        screenheight = 0;
        graphicsThread = null;
        distKey = null;
        devKey = null;
        running = false;
        displaymodelist = null;
        pixelformatlist = null;
        displaymode = new DisplayMode(0, 0, 0, 0);
        numKeyboardControllers = 0;
    }

    protected synchronized void init()
    {
        super.init();
        eventQueue = Collections.synchronizedList(new LinkedList());
        glcontext = null;
        autoUpdate = true;
        running = false;
        portManager = new ControllerPortManagerImpl(0, null);
        graphicsThread = null;
    }

    public synchronized boolean initRuntime()
    {
        String dev = null;
        String dist = null;
        try
        {
            java.io.InputStream in = new FileInputStream(new File(PlatformInfo.getCommonDirectory(), "identity_dev"));
            Properties props = new Properties();
            props.load(in);
            dev = props.getProperty("identity");
        }
        catch(IOException e) { }
        Resource res = getClassLoader().getArchive().getResource("/META-INF/KEEL_IDENTITY");
        if(res != null)
        {
            byte bytes[] = (byte[])res.getContent();
            dist = new String(bytes);
        }
        return initRuntime(dist, dev);
    }

    protected boolean initRuntime(String dist, String dev)
    {
        return false;
    }

    public void setAutoUpdate(boolean b)
    {
        autoUpdate = b;
    }

    public boolean isAutoUpdate()
    {
        return autoUpdate;
    }

    public void yield()
    {
    }

    public boolean isForeProcess()
    {
        return foreprocess;
    }

    public void run()
    {
        if(running)
            throw new IllegalStateException("already running");
        running = true;
        int loopCount = 0;
        while(running) 
        {
            Event event1;
            while((event1 = peekEvent()) != null) 
                processEvent(event1);
            if(autoUpdate)
                kickPaint();
            yield();
        }
        running = false;
    }

    public void stop()
    {
        running = false;
    }

    public synchronized void repaint()
    {
        Event e = new ApplicationEvent(2100);
        eventQueue.add(e);
    }

    public void exitWithFatalError(String message)
    {
        StringTokenizer tokenizer = new StringTokenizer(message, "\n");
        Object messageArray[] = new Object[tokenizer.countTokens()];
        for(int i = 0; tokenizer.hasMoreTokens(); i++)
            messageArray[i] = tokenizer.nextToken();

        JOptionPane pane = new JOptionPane(((Object) (messageArray)), 0, -1);
        JDialog dialog = pane.createDialog(null, "Fatal Error");
        dialog.show();
        dialog.toFront();
        disposeDisplay();
        System.exit(1);
    }

    public DisplayMode[] getDisplayModeList()
    {
        return (DisplayMode[])displaymodelist.clone();
    }

    public PixelFormat[] getPixelFormatList(int renderer)
    {
        ArrayList a = new ArrayList(pixelformatlist.length);
        for(int l = 0; l < pixelformatlist.length; l++)
            if((pixelformatlist[l].getRendererInfo() & renderer) != 0)
                a.add(pixelformatlist[l]);

        return (PixelFormat[])a.toArray(new PixelFormat[0]);
    }

    public int getWidth()
    {
        return screenwidth;
    }

    public int getHeight()
    {
        return screenheight;
    }

    public boolean isWindowMode()
    {
        return windowmode;
    }

    public synchronized void createWindow(String title, int width, int height)
    {
        if(graphicsThread == Thread.currentThread())
        {
            throw new IllegalStateException("Graphics is active");
        } else
        {
            disposeGraphics();
            _createWindow(title, width, height);
            windowmode = true;
            screenwidth = width;
            screenheight = height;
            updatePixelFormat();
            return;
        }
    }

    public boolean isDisplayAvailable(DisplayMode d)
    {
        return _isDisplayAvailable(d);
    }

    public DisplayMode getCurrentDisplayMode()
    {
        return displaymode;
    }

    public synchronized void createDisplay(DisplayMode d)
    {
        if(graphicsThread == Thread.currentThread())
            throw new IllegalStateException("Graphics is active");
        if(d == null)
            throw new NullPointerException("DisplayMode is null");
        if(!isDisplayAvailable(d))
        {
            throw new IllegalArgumentException("Illegal DisplayMode");
        } else
        {
            disposeGraphics();
            _createDisplay(d);
            windowmode = false;
            screenwidth = d.getWidth();
            screenheight = d.getHeight();
            updatePixelFormat();
            return;
        }
    }

    public void createGraphics(PixelFormat pf)
    {
        if(graphicsThread == Thread.currentThread())
            throw new IllegalStateException("Graphics is active");
        if(pf == null)
            throw new NullPointerException("PixelFormat is null");
        if(!pf.isAvailable())
            throw new IllegalArgumentException("Illegal PixelFormat");
        if((pf.getRendererInfo() & 1) != 0)
        {
            long ref = _createGraphics(pf);
            if(ref == 0L)
                throw new RuntimeException("Createing Graphics Context failed.");
            try
            {
                glcontext = new GLContextRuntimeImpl(ref);
            }
            catch(Exception e)
            {
                e.printStackTrace();
                return;
            }
        } else
        if((pf.getRendererInfo() & 2) != 0)
            try
            {
                glcontext = makeSoftGLContext(getScreenPtr(), getWidth(), getHeight());
            }
            catch(Exception e)
            {
                e.printStackTrace();
                return;
            }
        String s = GLGraphics.getGLVersion();
        GLGraphics g = getGraphics();
        if(g != null)
        {
            try
            {
                application.initGraphics(g);
                swapBuffers();
            }
            catch(Exception e)
            {
                System.err.println("Exception in Application.init!!");
                e.printStackTrace();
            }
            g.dispose();
        }
    }

    GLContext makeSoftGLContext(int ptr, int w, int h)
    {
        return new SoftGLContext(ptr, w, h);
    }

    public synchronized void disposeDisplay()
    {
        if(graphicsThread == Thread.currentThread())
            throw new IllegalStateException("Graphics is active");
        disposeGraphics();
        _disposeDisplay();
        screenwidth = 0;
        screenheight = 0;
        if(pixelformatlist != null)
        {
            for(int l = 0; l < pixelformatlist.length; l++)
                pixelformatlist[l].dispose();

            pixelformatlist = null;
        }
    }

    public void disposeGraphics()
    {
        if(glcontext != null)
        {
            glcontext.dispose();
            glcontext = null;
        }
    }

    public GLGraphics getGraphics()
    {
        if(glcontext != null)
            return glcontext.getGraphics();
        else
            return null;
    }

    void swapBuffers()
    {
        _swapBuffers();
    }

    public void setVSync(boolean flag)
    {
    }

    public void processEvent(Event event)
    {
        if(event instanceof ControllerEvent)
        {
            ControllerEvent ce = (ControllerEvent)event;
            ControllerPort port = ce.getPort();
            if(port != null)
                port.processEvent(ce);
            Controller controller = ce.getController();
            controller.processEvent(ce);
        } else
        if(event instanceof ControllerPortEvent)
        {
            ControllerPortEvent cpe = (ControllerPortEvent)event;
            switch(cpe.getID())
            {
            case 2200: 
                attachControllerPort(cpe.getPort(), cpe.getControllerIndex(), true);
                break;

            case 2201: 
                attachControllerPort(cpe.getPort(), -1, true);
                break;

            case 2202: 
                scanControllerDevices();
                refreshControllerMenu();
                break;

            case 2203: 
                startControllerConfig();
                break;
            }
        } else
        if(event instanceof ApplicationEvent)
            switch(event.getID())
            {
            case 2100: 
                if(!autoUpdate)
                    kickPaint();
                break;

            case 2101: 
                application.quitRequested();
                break;

            case 2102: 
                foreprocess = true;
                if(portManager != null)
                    portManager.setEnabled(true);
                break;

            case 2103: 
                foreprocess = false;
                if(portManager != null)
                    portManager.setEnabled(false);
                break;
            }
        else
            super.processEvent(event);
    }

    public synchronized Event peekEvent()
    {
        if(eventQueue.size() > 0)
        {
        	if(mouseFix)
        	{
        		mouseFix=false;
        		return null;
        	}
        	return (Event)eventQueue.remove(0);
        }
        Event event1;
        while((event1 = _peekEvent()) != null) 
            eventQueue.add(event1);
        if(portManager != null)
        {
            portManager.updateAll();
            portManager.peekEvent(eventQueue);
        }
        if(eventQueue.size() > 0)
        {
        	if(mouseFix)
        	{
        		mouseFix=false;
        		return null;
        	}
        	Event tt=(Event)eventQueue.remove(0); 
        	if(tt instanceof MouseEvent && tt.getID()==MouseEvent.MOUSE_PRESSED)
        		mouseFix=true; 
            return tt;
        }
        else
            return null;
    }

    public synchronized void postEvent(Event event)
    {
        eventQueue.add(event);
    }

    public void setCursorVisible(boolean flag)
    {
    }

    public void enableInputMethods(boolean b)
    {
        if(inputMethodEnabled != b)
        {
            inputMethodEnabled = b;
            _enableInputMethods(inputMethodEnabled);
        }
    }

    public void setInputMethodPassiveMode(PassiveInputMethodRequests passiveinputmethodrequests, boolean flag)
    {
    }

    public boolean setInputMethodActiveMode(ActiveInputMethodRequests reqs)
    {
        return false;
    }

    protected void _enableInputMethods(boolean flag)
    {
    }

    public void useController(int numPorts, ControllerDescriptor descriptor, int numKeyboard, boolean useMenu)
    {
        if(descriptor == null)
            throw new NullPointerException("descriptor is null");
        numKeyboardControllers = numKeyboard;
        useControllerMenu = useMenu;
        portManager = new ControllerPortManagerImpl(numPorts, descriptor);
        portManager.loadConversions();
        for(int i = 0; i < numKeyboardControllers; i++)
            portManager.addCandidateController(createKeyboardController(descriptor, i));

        scanControllerDevices();
        portManager.loadPorts();
        if(windowmode)
            refreshControllerMenu();
        usingdescriptors = (new ControllerDescriptor[] {
            descriptor
        });
    }

    public ControllerPortManager getControllerPortManager()
    {
        return portManager;
    }

    public int[] getAttachedControllerIndexes()
    {
        int result[] = new int[portManager.getNumPorts()];
        java.util.List controllerList = Arrays.asList(candidateControllers);
        for(int i = 0; i < result.length; i++)
        {
            ControllerPort port = portManager.getPort(i);
            if(port != null)
                result[i] = controllerList.indexOf(port.getController());
            else
                result[i] = -1;
        }

        return result;
    }

    public String[] getCandidateControllerNames()
    {
        String result[] = new String[candidateControllers.length];
        for(int i = 0; i < result.length; i++)
            result[i] = candidateControllers[i].getName();

        return result;
    }

    protected void scanControllerDevices()
    {
        ControllerDeviceManager deviceManager = ControllerDeviceManager.getManager();
        java.util.List deviceList = deviceManager.scanControllerDevices();
        synchronized(portManager)
        {
            if(deviceControllerList != null)
            {
                Controller ct;
                for(Iterator it = deviceControllerList.iterator(); it.hasNext(); portManager.detachAll(ct))
                {
                    ct = (Controller)it.next();
                    portManager.removeCandidateController(ct);
                }

            }
            deviceControllerList = new ArrayList();
            for(int i = 0; i < deviceList.size(); i++)
            {
                ControllerDeviceImpl device = (ControllerDeviceImpl)deviceList.get(i);
                Controller ct = device.createController(portManager.getDescriptor());
                ct.setName(device.getConfig().getName());
                deviceControllerList.add(ct);
                portManager.addCandidateController(ct);
            }

            portManager.reattachAll();
            candidateControllers = portManager.getCandidateControllers();
        }
    }

    protected void attachControllerPort(int port, int index, boolean save)
    {
        if(index >= 0 && index < candidateControllers.length)
            portManager.getPort(port).attach(candidateControllers[index]);
        else
            portManager.getPort(port).detach();
        if(save)
            portManager.savePorts();
    }

    private Controller createKeyboardController(ControllerDescriptor descriptor, int keyboardIndex)
    {
        keel.runtime.ctrl.KeyboardDeviceConversion conversion = ControllerConfigSet.getConfigSet().getKeyboardDeviceConversion(keyboardIndex, descriptor);
        Controller ct = getKeyboardDevice().createController(descriptor, conversion);
        ct.setName("KEYBOARD CONTROLLER " + keyboardIndex);
        return ct;
    }

    protected void refreshControllerMenu()
    {
    }

    protected void startControllerConfig()
    {
    }

    public KeyboardDevice getKeyboardDevice()
    {
        if(keyboardDevice == null)
            keyboardDevice = new KeyboardDeviceImpl();
        return keyboardDevice;
    }

    protected int getSysCursorWidth()
    {
        return -1;
    }

    protected int getSysCursorHeight()
    {
        return -1;
    }

    protected Cursor createNativeCursor(Image image, int pixels[], int width, int i, int j, int k)
    {
        return null;
    }

    public Cursor createCursor(Image cursor, int hotspotX, int hotspotY)
    {
        Image image = cursor;
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        java.awt.Component c = new Canvas();
        MediaTracker tracker = new MediaTracker(c);
        tracker.addImage(cursor, 0);
        try
        {
            tracker.waitForAll();
        }
        catch(InterruptedException e) { }
        int width = cursor.getWidth(c);
        int height = cursor.getHeight(c);
        if(tracker.isErrorAny() || width < 0 || height < 0)
            hotspotX = hotspotY = 0;
        int nativeWidth = getSysCursorWidth();
        int nativeHeight = getSysCursorHeight();
        if(nativeWidth != -1 && nativeHeight != -1 && (nativeWidth != width || nativeHeight != height))
        {
            cursor = cursor.getScaledInstance(nativeWidth, nativeHeight, 1);
            tracker.addImage(cursor, 1);
            try
            {
                tracker.waitForAll();
            }
            catch(InterruptedException e) { }
            width = nativeWidth;
            height = nativeHeight;
        }
        if(hotspotX >= width || hotspotY >= height || hotspotX < 0 || hotspotY < 0)
            throw new IndexOutOfBoundsException("invalid hotSpot");
        int pixels[] = new int[width * height];
        java.awt.image.ImageProducer ip = cursor.getSource();
        PixelGrabber pg = new PixelGrabber(ip, 0, 0, width, height, pixels, 0, width);
        try
        {
            pg.grabPixels();
        }
        catch(InterruptedException e) { }
        return createNativeCursor(image, pixels, width, height, hotspotX, hotspotY);
    }

    public void setCursor(Cursor cursor1)
    {
    }

    public AudioPlayer getMpegAudioPlayer()
    {
        return null;
    }

    protected File getCommonDirectory()
    {
        return new File(".");
    }

    protected void kickPaint()
    {
        GLGraphics g = getGraphics();
        if(g != null)
        {
            try
            {
                application.update(g);
                g.swapBuffers();
            }
            catch(Exception e)
            {
                System.err.println("An exception occured in KeelRuntime event loop");
                e.printStackTrace();
            }
            g.dispose();
        }
    }

    protected abstract Event _peekEvent();

    protected abstract void updatePixelFormat();

    protected abstract void _createWindow(String s, int i, int j);

    protected abstract boolean _isDisplayAvailable(DisplayMode displaymode1);

    protected abstract void _createDisplay(DisplayMode displaymode1);

    protected abstract void _disposeDisplay();

    protected abstract long _createGraphics(PixelFormat pixelformat);

    protected abstract boolean _makeCurrent();

    protected abstract void _swapBuffers();

    protected abstract void _free();

    protected abstract int getScreenPtr();

    protected static final String KEYBOARD_CONTROLLER = "KEYBOARD CONTROLLER ";
    protected boolean autoUpdate;
    protected boolean foreprocess;
    protected GLContext glcontext;
    protected transient java.util.List eventQueue;
    protected int screenwidth;
    protected int screenheight;
    Thread graphicsThread;
    boolean inputMethodEnabled;
    ControllerDescriptor usingdescriptors[];
    private String distKey;
    private String devKey;
    boolean running;
    long starttime;
    protected DisplayMode displaymodelist[];
    protected PixelFormat pixelformatlist[];
    protected DisplayMode displaymode;
    private boolean windowmode;
    protected ControllerPortManagerImpl portManager;
    private java.util.List deviceControllerList;
    protected Controller candidateControllers[];
    protected boolean useControllerMenu;
    private int numKeyboardControllers;
    protected KeyboardDeviceImpl keyboardDevice;
    
    boolean mouseFix = false;
}
